#include <JXQCore/JXQGlobal>
#ifdef J_OS_WIN

#include "jthread.h"
#include "jthread_p.h"
#include <thread>

namespace JXQ
{

#ifdef __GNUC__
WINAPI
#endif
DWORD JThreadPrivate::run(LPVOID lpThreadParameter)
{
	auto d_ptr = J_RCT(JThreadPrivate*, lpThreadParameter);
	int res = 0;

    d_ptr->q_ptr->run();

	CloseHandle(d_ptr->m_handle);

	d_ptr->m_handle = nullptr;
	d_ptr->finish(); //!!!!!!!!!!!!
	return res;
}

JThread::~JThread()
{
	if( d_ptr->m_handle != nullptr /*and not d_ptr->m_isDetach*/ )
        jError() << "## Warning: JThread: destruct before a thread terminates. call detach() to mask warning";

    if( not --d_ptr->m_ref )
		delete d_ptr;
}

void JThread::start() noexcept
{
	if( d_ptr->m_handle != nullptr )
		return;

    ++d_ptr->m_ref;
	DWORD far id;
    HANDLE handle = CreateThread(nullptr, d_ptr->m_stackSize, &JThreadPrivate::run,
								 d_ptr, 0, &id);

	if( handle == nullptr )
		jError() << "JThread: CreateThread: return NULL";
	else
		d_ptr->m_handle = handle;
}

bool JThread::isFinished() const
{
	return d_ptr->m_handle == nullptr;
}

JTid JThread::selfID()
{
	return GetCurrentThreadId();
}

void JThread::usleep(uint32_t usecs)
{
	std::this_thread::sleep_for(std::chrono::microseconds(usecs));
}

void JThread::msleep(uint32_t msecs)
{
	Sleep(msecs);
}

void JThread::sleep(uint32_t secs)
{
	Sleep(secs*1000);
}

void JThread::sleep(uint32_t secs, uint32_t msecs)
{
	Sleep(secs*1000 + msecs);
}

void JThread::sleep(uint32_t secs, uint32_t msecs, uint32_t usecs)
{
	std::this_thread::sleep_for
			(std::chrono::microseconds(secs*1000000LL + msecs*1000 + usecs));
}

JXQLIB_EXPORT int JThread::getCPUCoreCount()
{
	SYSTEM_INFO sysInfo;
	GetSystemInfo(&sysInfo);
	return sysInfo.dwNumberOfProcessors;
}

} //namespace JXQ


#endif // windows
